package org.example;

import java.util.concurrent.*;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;

/**
 * Copyright (c) 2023-2033 All Rights Reserved
 *
 * 1. 线程池创建：
 * 1) Executors 类提供静态方法创建线程、通过 ThreadFactory 创建线程
 * 2) ThreadPoolExecutor 构造方法创建自定义线程池
 *
 * 2. 线程池使用：
 * 1) execute()：可以执行 runnable 任务，有异常会抛出
 * 2) submit()：可以执行 runnable/callable 任务，执行后返回 Future 对象，通过 future.get() 可以获取 callable 任务的返回值和异常信息，有异常不会主动抛出
 * 3) shutdown()
 *
 * 3. 线程池异常处理
 * execute(runnable):
 * 1) 在 Runnable 任务中添加 try catch 捕获执行过程中的异常
 * 2) 通过线程 thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()) 重写 uncaughtException(Thread t, Throwable e) 捕获异常
 * 3) 创建线程工厂 ThreadFactory 重写 newThread(Runnable r) 指定创建线程的方法，线程执行 r，并设置异常处理 Handler，通过线程工厂创建线程池实现批量设置线程异常处理
 * 4) 重写 afterExecute()
 *
 * submit(runnable):
 * 1) 在 Runnable 任务中添加 try catch 捕获执行过程中的异常
 * 2) 只能通过 Future.get() 捕获异常
 *
 * https://blog.csdn.net/WLFIGHTER/article/details/113773874
 * https://www.cnblogs.com/ncy1/articles/11629933.html
 * https://blog.csdn.net/qq_32166627/article/details/118968373
 * https://blog.csdn.net/qq_45076180/article/details/114552567
 *
 * @date: 2023/5/11
 */
public class ThreadPoolExecutorTest {
    public static void main(String[] args) throws Exception {
        executorsMethod(); // 线程池创建
        threadPoolExecutorSelfDefine(); // 线程池创建
        executeTest();  // ExecutorService.execute()
        submitTest();   // ExecutorService.submit()
        threadPoolMethod(); // 线程池方法
    }

    // Executors.静态方法 创建线程
    public static void executorsMethod() {
        // 1. 通过一个参数创建
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        ExecutorService executorService1 = Executors.newFixedThreadPool(5);
        ExecutorService executorService2 = Executors.newCachedThreadPool();
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(6);

        // 2. 通过线程工厂创建
        ThreadFactory threadFactory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                // 1) 通过默认线程工厂创建线程
                Thread thread = Executors.defaultThreadFactory().newThread(r);
                // 2) 通过任务 r 直接创建线程
                Thread thread1 = new Thread(r);
                return thread;
            }
        };
        Executors.newFixedThreadPool(3, threadFactory);

        // 3. 线程工厂 lambda 表达式
        ThreadFactory threadFactory1 = (r) -> {
            // 重新指定任务的 run() 执行内容
            Thread thread = new Thread(() -> {
                System.out.println("Executors.ThreadFactory");
            });
            return thread;
        };
        ExecutorService executorService3 = Executors.newSingleThreadExecutor(threadFactory1);
        executorService3.execute(() -> {
            System.out.println("Executors.ThreadFactory Runnable");
        });
        executorService3.shutdown();
    }

    // ThreadPoolExecutor 创建自定义线程池
    public static void threadPoolExecutorSelfDefine() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1,
                1000L, MILLISECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory());

        Runnable runnable = () -> { System.out.println("Self Define threadPoolExecutor"); };
        threadPoolExecutor.execute(runnable);
    }

    // execute() 只能执行 runnable，无返回值，异常信息直接抛出
    public static void executeTest() {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.execute(() -> System.out.println("executeTest"));

        // 1. 在 Runnable 添加 try catch 捕获异常，不会打印，有异常终止后续代码运行
        executorService.execute(() -> {
            try {
                System.out.println("thread execute before exception");
                throw new RuntimeException("errRunnable exception");
            } catch (Exception e) {
                System.out.println("e = " + e);
                System.out.println("e.getMessage() = " + e.getMessage());
//                e.printStackTrace(); // java.lang.RuntimeException: errRunnable exception
            }
        });
        // 结果：
        // thread execute before exception
        // e = java.lang.RuntimeException: errRunnable exception
        // e.getMessage() = errRunnable exception

        // 定义抛出异常的任务
        Runnable runnable = () -> {
            System.out.println("thread execute before exception");
            throw new RuntimeException("errRunnable exception");
        };

        // 2. 通过 thread 方法捕获异常
        ThreadFactory threadFactory1 = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
                thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
                    @Override
                    public void uncaughtException(Thread t, Throwable e) {
                        System.out.println("t = " + t + ", e = " + e);
                        System.err.println("thread.setUncaughtExceptionHandler catch exception for execute : " + e.getMessage());
                    }
                });
                return thread;
            }
        };
        ExecutorService executorService2 = Executors.newSingleThreadExecutor(threadFactory1);
        executorService2.execute(runnable);
        executorService2.shutdown();
        // thread execute before exception
        // t = Thread[#34,Thread-1,5,main], e = java.lang.RuntimeException: errRunnable exception
        // thread.setUncaughtExceptionHandler catch exception for execute : errRunnable exception

        // 3. lambda 表达式
        ThreadFactory threadFactory = r -> {
            Thread thread = Executors.defaultThreadFactory().newThread(r);
            thread.setUncaughtExceptionHandler((t,e) -> {
                System.err.println("catch exception for execute : " + e.getMessage());
            });
            return thread;
        };

        ExecutorService executorService1 = Executors.newFixedThreadPool(2, threadFactory);
        executorService1.execute(runnable);
        executorService.shutdown();
    }

    // submit() 可以执行 runnable 和 callable
    private static void submitTest() throws Exception {
        // 1. 定义任务
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                // 1) Runnable 任务
                System.out.println("Runnable task submit");
            }
        };
        // 2) Callable 任务
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println("Callable task submit");
                return "callable result";
            }
        };
        // 3) 异常 Runnable 任务
        Runnable errRunnable = () -> {
            System.out.println("errRunnable task submit");
            throw new RuntimeException("errRunnable exception");
        };
        // 4) 异常 Callable 任务
        Callable<String> errCallable = () -> {
            System.out.println("errCallable task submit");
            throw new RuntimeException("errCallable exception");
        };

        ExecutorService executorService = Executors.newFixedThreadPool(2);
        // 普通任务处理
        Future<?> runnableFuture = executorService.submit(runnable);                 // Runnable task submit
        System.out.println("submit runnableFuture.get() : " + runnableFuture.get()); // submit runnableFuture.get() : null
        // 提交 callable 可以获取返回结果
        Future<String> callableFuture = executorService.submit(callable);            // Callable task submit
        System.out.println("submit callableFuture.get() : " + callableFuture.get()); // submit callableFuture.get() : callable result

        // 异常任务处理：executorService.submit(errRunnable/callable) 都不会抛出异常，必须要通过 future.get()才能看到异常信息
//        Future<?> errRunnableFuture = executorService.submit(errRunnable);   // errRunnable task submit，不会抛出异常信息
//        System.out.println("submit errRunnableFuture.get() : " + errRunnableFuture.get()); // 执行后无打印，直接抛出异常

        Future<String> errCallableFuture = executorService.submit(errCallable);  // errCallable task submit
//        System.out.println("future1.get() : " + errCallableFuture.get()); // 执行后无打印，直接抛出异常
        try {
            errCallableFuture.get();
        } catch (Exception e) {
            System.out.println("errCallableFuture.get() Exception: " + e.getMessage());  // 通过 try catch 捕获 future.get()
        }

        executorService.shutdown();

        // 线程设置异常处理后通过 submit() 执行任务 runnable/callable 和上述效果一样
        ThreadFactory threadFactory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
                thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
                    @Override
                    public void uncaughtException(Thread t, Throwable e) {
                        System.out.println("t = " + t + ", e = " + e);
                    }
                });
                return thread;
            }
        };
        Executors.newSingleThreadExecutor(threadFactory).submit(errRunnable); // 不会抛出异常
        Executors.newSingleThreadExecutor(threadFactory).submit(errCallable); // 不会抛出异常

        try {
            Executors.newSingleThreadExecutor(threadFactory).submit(errRunnable).get();
            Executors.newSingleThreadExecutor(threadFactory).submit(errCallable).get();
        } catch (Exception e) {
            // 效果和上一模块相同
            System.out.println("e.getMessage() = " + e.getMessage()); // e.getMessage() = java.lang.RuntimeException: errRunnable exception
        }
    }


    private static void threadPoolMethod() {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.execute(() -> {});
        executorService.submit(() -> {});
        executorService.shutdown();
        executorService.shutdownNow();
        executorService.isShutdown();
        executorService.isTerminated();

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1,
                1000L, MILLISECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory());
        threadPoolExecutor.execute(()->{});
        threadPoolExecutor.submit(() -> {});
        threadPoolExecutor.remove(() -> {});
        threadPoolExecutor.getCorePoolSize();
        threadPoolExecutor.setKeepAliveTime(1000L, SECONDS);
        threadPoolExecutor.shutdown();
        threadPoolExecutor.shutdownNow();
        threadPoolExecutor.isShutdown();
        threadPoolExecutor.isTerminated();

        new ThreadPoolExecutor(1, 1,
                1000L, MILLISECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory()) {
            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
                System.out.println("ThreadPoolExecutor afterExecute Throwable.getMessage(): " + t.getMessage());
            }
        };
    }
}
